package top.yokey.shopai.zcom.voice;

import android.app.Service;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.appcompat.widget.AppCompatButton;

@SuppressWarnings("ALL")
public class VoiceButton extends AppCompatButton implements VoiceHelp.StateListener {

    private static final int STATE_NORMAL = 1;
    private static final int STATE_RECORDING = 2;
    private static final int STATE_WANT_2_CANCEL = 3;
    private static final int DISTANCE_Y_CANCEL = 50;
    private static final int MSG_AUDIO_PREPARED = 0X110;
    private static final int MSG_VOICE_CHANGED = 0X111;
    private static final int MSG_DIALOG_DIMISS = 0X112;

    private float mTime = 0;
    private boolean mReady = false;
    private int mCurState = STATE_NORMAL;
    private boolean isRecording = false;
    private VoiceDialog voiceDialog = null;
    private recorderListener recorderListener = null;

    public VoiceButton(Context context) {

        this(context, null);

    }

    public VoiceButton(Context context, AttributeSet attrs) {

        super(context, attrs);
        voiceDialog = new VoiceDialog(getContext());
        VoiceHelp.get().setOnStateListener(this);
        setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                mReady = true;
                VoiceHelp.get().prepare();
                return false;
            }
        });

    }

    @Override
    public void prepared() {

        handler.sendEmptyMessage(MSG_AUDIO_PREPARED);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int action = event.getAction();
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                Vibrator vibrator = (Vibrator) getContext().getSystemService(Service.VIBRATOR_SERVICE);
                vibrator.vibrate(100);
                reset();
                isRecording = true;
                changeState(STATE_RECORDING);
                break;
            case MotionEvent.ACTION_MOVE:
                if (isRecording) {
                    if (want2Cancel(x, y)) {
                        changeState(STATE_WANT_2_CANCEL);
                    } else {
                        changeState(STATE_RECORDING);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if (!mReady) {
                    reset();
                    return super.onTouchEvent(event);
                }
                if (!isRecording || mTime < 1f) {
                    voiceDialog.tooShort();
                    VoiceHelp.get().cancel();
                    handler.sendEmptyMessageDelayed(MSG_DIALOG_DIMISS, 1300);
                } else if (mCurState == STATE_RECORDING) {
                    voiceDialog.dismiss();
                    VoiceHelp.get().release();
                    if (recorderListener != null) {
                        recorderListener.onFinish(mTime, VoiceHelp.get().getFilePath());
                    }
                } else if (mCurState == STATE_RECORDING) {
                    voiceDialog.dismiss();
                } else if (mCurState == STATE_WANT_2_CANCEL) {
                    voiceDialog.dismiss();
                    VoiceHelp.get().cancel();
                }
                reset();
                break;
            case MotionEvent.ACTION_CANCEL:
                if (!mReady) {
                    reset();
                    return super.onTouchEvent(event);
                }
                if (!isRecording || mTime < 0.6f) {
                    voiceDialog.tooShort();
                    VoiceHelp.get().cancel();
                    handler.sendEmptyMessageDelayed(MSG_DIALOG_DIMISS, 1300);
                } else if (mCurState == STATE_RECORDING) {
                    voiceDialog.dismiss();
                    VoiceHelp.get().release();
                    if (recorderListener != null) {
                        recorderListener.onFinish(mTime, VoiceHelp.get().getFilePath());
                    }
                } else if (mCurState == STATE_RECORDING) {
                    voiceDialog.dismiss();
                } else if (mCurState == STATE_WANT_2_CANCEL) {
                    voiceDialog.dismiss();
                    VoiceHelp.get().cancel();
                }
                reset();
                break;
        }
        return super.onTouchEvent(event);

    }

    private void reset() {

        isRecording = false;
        mReady = false;
        changeState(STATE_NORMAL);
        mTime = 0;

    }

    private boolean want2Cancel(int x, int y) {

        if (x < 0 || x > getWidth()) {
            return true;
        }
        if (y < -DISTANCE_Y_CANCEL || y > getHeight() + DISTANCE_Y_CANCEL) {
            return true;
        }
        return false;

    }

    private void changeState(int state) {

        if (mCurState != state) {
            mCurState = state;
            switch (state) {
                case STATE_NORMAL:
                    setText("按住说话");
                    break;
                case STATE_RECORDING:
                    setText("松开结束");
                    if (isRecording) {
                        voiceDialog.recording();
                    }
                    break;
                case STATE_WANT_2_CANCEL:
                    setText("松开手指，取消发送");
                    voiceDialog.want2Cancel();
                    break;
            }
        }

    }

    public void setAudioFinishRecorderListener(recorderListener recorderListener) {

        this.recorderListener = recorderListener;

    }

    public interface recorderListener {

        void onFinish(float seconds, String filePath);
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_AUDIO_PREPARED:
                    voiceDialog.showRecordingDialog();
                    isRecording = true;
                    new Thread(runnable).start();
                    break;
                case MSG_VOICE_CHANGED:
                    voiceDialog.setLevel(VoiceHelp.get().getLevel(7));
                    break;
                case MSG_DIALOG_DIMISS:
                    voiceDialog.dismiss();
                    break;
            }
        }
    };


    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            while (isRecording) {
                try {
                    Thread.sleep(100);
                    mTime += 0.1;
                    handler.sendEmptyMessage(MSG_VOICE_CHANGED);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };


}
